package cn.hxzy.commonUser.service.impl;

import cn.hxzy.common.Eeception.DiyException;
import cn.hxzy.common.Eeception.GlobalExceptionHandler;
import cn.hxzy.common.Result;
import cn.hxzy.common.util.JwtUtils;
import cn.hxzy.entity.userEntity.User;
import cn.hxzy.commonUser.mapper.UserMapper;
import cn.hxzy.commonUser.service.UserService;
import cn.hxzy.entity.userEntity.vo.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ao.Li
 * @since 2023-06-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

//    @Autowired
//    private AuthenticationManager authenticationManager;

    @Autowired
    @Qualifier("CodeProvider")
    private AuthenticationProvider authenticationManager2;

    @Autowired
    @Qualifier("redis")
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Result login(User user) {
        //不需要连接数据库
        //1、把登录时候的用户名与密码封装成一个UsernamePasswordAuthenticationToken对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserPhone(), user.getUserPwd());
        //3、通过AuthenticationManager的authenticate方法来进行用户认证，判断密码，奥森提
        try{
            Authentication authenticate = authenticationManager2.authenticate(authenticationToken);
            //判断认证后的对象是否为空。空则为认证失败
            if (Objects.isNull(authenticate)){
                return new GlobalExceptionHandler().error(new DiyException(2555, "未登录,请登录"));
            }
            //如果认证成功，就从authenticate对象的getPrincipal方法中拿到认证通过后的登录用户对象
            LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
            //得到用户编号
            String userId = loginUser.getUser().getUserId().toString();
            //生成令牌
            String jwt = JwtUtils.createJWT(userId);
            //1、把登录用户存入redis
            redisTemplate.opsForValue().set("login:"+userId, loginUser);
            return Result.ok().message("登录成功").data("token",jwt).data("userName",user.getUserName()).data("userPhone",user.getUserPhone()).data("userId",user.getUserId());
        }catch (Exception e){
            e.printStackTrace();
            return new GlobalExceptionHandler().error(new DiyException(555, "密码有误！"));
        }
    }

    @Override
    public Result loginByCode(User user) {
        //不需要连接数据库
        //1、把登录时候的用户名与密码封装成一个UsernamePasswordAuthenticationToken对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserPhone(), user.getCode());
        //3、通过AuthenticationManager的authenticate方法来进行用户认证，判断密码
        try{
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("user_phone",user.getUserPhone());
            User one = userMapper.selectOne(wrapper);
            if (Objects.isNull(one)){
                this.registered(user);
            }
            Authentication authenticate = authenticationManager2.authenticate(authenticationToken);
            //判断认证后的对象是否为空。空则为认证失败
            if (Objects.isNull(authenticate)){
                return new GlobalExceptionHandler().error(new DiyException(2555, "未登录,请登录"));
            }
            //如果认证成功，就从authenticate对象的getPrincipal方法中拿到认证通过后的登录用户对象
            LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
            //得到用户编号
            String userId = loginUser.getUser().getUserId().toString();
            //生成令牌
            String jwt = JwtUtils.createJWT(userId);
            //1、把登录用户存入redis
            redisTemplate.opsForValue().set("login:"+userId, loginUser);
            return Result.ok().message("登录成功").data("token",jwt).data("userName",user.getUserName()).data("userPhone",user.getUserPhone()).data("userId",user.getUserId());
        }catch (Exception e){
            return new GlobalExceptionHandler().error(new DiyException(555, "密码有误！"));
        }
    }


    @Override
    public Result logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userid = loginUser.getUser().getUserId();
        Boolean delete = redisTemplate.delete("login:" + userid);
        if (delete){
            return Result.ok().message("退出成功").code(20000);
        }
        return Result.error().message("系统异常！退出失败！").data("token","");

    }

    @Override
    public Result status(HttpServletRequest request, HttpServletResponse response) {
        String jwt = request.getHeader("token");
        if (jwt==null){
            return Result.error().message("未登录");
        }
        try {
            Claims claims = JwtUtils.parseJWT(jwt);
            String userId = claims.getSubject();
            LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get("login:"+userId);
            return Result.ok().data("user",loginUser);
        } catch (Exception e) {
            return Result.error().message("系统异常！");
        }

    }

    @Override
    public Result registered(User user) {
        UUID uuid = UUID.randomUUID();
        String s = uuid.toString().replace("-", "");
        String s1 = s.substring(0, 8);

        if (user.getRoleId().equals("1")){
            user.setUserId("SJ"+s1);
        }else {
            user.setUserId("HZ"+s1);
        }
        int insert = userMapper.insert(user);
        if (insert>0){
            return Result.ok().message("注册成功");
        }
        return Result.error().message("注册失败");
    }

    //    远程调用 马奎志
//    @Override
//    public User selectOneByPhone(String phone) {
//        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        wrapper.eq("user_phone",phone);
//        User user = userMapper.selectOne(wrapper);
//        if (user != null){
//           return user;
//        }
//        return null;
//    }

    /**
     * 修改密码
     * @param
     * @return
     */
    @Override
    public Boolean updatePwdById(String userId,String oldPwd, String newPwd) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_id",userId);
        User user = userMapper.selectOne(wrapper);
        if (!user.getUserPwd().equals(oldPwd)) {
            return false;
        }

        //设置新密码
        User u = new User();
        u.setUserPwd(newPwd);
        u.setUserId(userId);
        //修改密码
        int i = userMapper.update(u,wrapper);
        if (i > 0) {
            return true;
        }
        return false;
    }


    @Override
    public User loginByPwd(User user) {
        if (Objects.isNull(user)) {
            return null;
        }

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_phone",user.getUserPhone());
        wrapper.eq("user_pwd",user.getUserPwd());

        User u = userMapper.selectOne(wrapper);
        if (!Objects.isNull(u)) {
            return u;
        }
        return null;
    }

}
